﻿using System;
using System.Linq;
using System.Collections.Generic;

namespace HashFoo.Core
{
    /// <summary>
    /// Reflection helpers
    /// </summary>
    public static class ReflectionUtil
    {
        /// <summary>
        /// Checks if a type inherits from a specific open generic type.  Both types should be a class.
        /// </summary>
        /// <remarks>
        /// Each type should be a class type since we need to walk an inheritance hierachry.
        /// For interfaces, we should probably create a new function of ImplementsGenericInterface.  DMF 20111130
        /// </remarks>
        /// <param name="typeToCheck"></param>
        /// <param name="genericType"></param>
        /// <returns></returns>
        public static bool IsOfGenericBaseType(this Type typeToCheck, Type genericType)
        {
            if (typeToCheck == null) throw new ArgumentNullException("typeToCheck");
            if (genericType == null) throw new ArgumentNullException("genericType");
            if (!genericType.IsClass) throw new ArgumentException("genericType needs to be a class type", "genericType");
            if (!typeToCheck.IsClass) throw new ArgumentException("typeToCheck should be a class type", "typeToCheck");

            while (typeToCheck != typeof(object))
            {
                if (typeToCheck.IsGenericType && typeToCheck.GetGenericTypeDefinition() == genericType) return true;

                typeToCheck = typeToCheck.BaseType;
                if (typeToCheck == null) return false;
            }

            return false;
        }

        /// <summary>
        /// Checks if a type if or inherits from an open generic type.  All types must be classes (in order to walk the inheritance hierarchy).
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="genericType"></param>
        /// <returns></returns>
        public static bool IsOfGenericBaseType<T>(Type genericType)
        {
            return typeof(T).IsOfGenericBaseType(genericType);
        }
    }
}